package com.googlecode.allinclusive.fw.core.data.input.excel.parser;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

import com.googlecode.allinclusive.fw.core.data.ExampleForm;
import com.googlecode.allinclusive.fw.core.data.Form;
import com.googlecode.allinclusive.fw.core.data.input.excel.config.ExcelColumn;
import com.googlecode.allinclusive.fw.core.data.input.excel.config.ExcelConfig;
import com.googlecode.allinclusive.fw.core.data.mapping.MappingParser;
import com.googlecode.allinclusive.fw.core.data.mapping.XMLExcelMappingParser;

public class POIExcelParser extends ExcelParser {

	/**
	 * 构造方法
	 * @param mappingParser 数据映射文件解析器 
	 * @param mappingLocations 映射文件
	 */
	public POIExcelParser(MappingParser mappingParser, String[] mappingLocations) {
		super(mappingParser, mappingLocations);
	}
	
	/**
	 * 解析数据文件并生成Form对象
	 * @param excelConfig 映射文件配置信息
	 * @param resource 数据文件 
	 * @param errors 解析&验证失败错误信息
	 * @return Form对象
	 */
	@Override
	public List<Form> parse(Class<? extends Form> formClass, ExcelConfig excelConfig, Resource resource, Collection<Object> errors) {
		
		List<Form> forms = new ArrayList<Form>();
		InputStream is = null;
		try {
			is = new BufferedInputStream(resource.getInputStream());
			
			XSSFWorkbook wb = new XSSFWorkbook(is);
			XSSFSheet sheet = wb.getSheetAt(excelConfig.getSheet());
			
			// parse sheet
			for (int i = excelConfig.getStartRow(); i <= sheet.getLastRowNum(); i++) {
				// parse row
				forms.add(parse(formClass, excelConfig, sheet.getRow(i), errors));
			}
		} catch (IOException ioe) {
			throw new RuntimeException(ioe);
		} finally {
			if (is != null) { try { is.close();} catch (IOException ioe) {}}
		}
		return forms;
	}
	
	/**
	 * 解析Excel行
	 * @param formClass Form对象类型
	 * @param excelConfig 映射文件配置信息
	 * @param row 单元行
	 * @param errors 解析&验证失败错误信息
	 * @return Form对象
	 */
	protected Form parse(Class<? extends Form> formClass, ExcelConfig excelConfig, XSSFRow row, Collection<Object> errors) {
		// create Form
		Form formObject = createForm(formClass);
		// loop
		for (int j = 0; j < excelConfig.getColumns().size(); j++) {
			// Excel Column Mapping
			ExcelColumn excelColumn = excelConfig.getColumns().get(j);
			// get cell value
			Object cellValue = null;
			XSSFCell cell = row.getCell(excelConfig.getStartCol() + j);
			switch (cell.getCellType()) {
			case XSSFCell.CELL_TYPE_NUMERIC :
				cellValue = cell.getNumericCellValue();
				break;
			case XSSFCell.CELL_TYPE_STRING :
				cellValue = cell.getRichStringCellValue().getString();
				break;
			case XSSFCell.CELL_TYPE_BLANK :
				// null
				cellValue = null;
				break;
			case XSSFCell.CELL_TYPE_BOOLEAN :
				cellValue = cell.getBooleanCellValue();
				break;
			default :
				cellValue = null;
			}
			// set property
			setProperty(formObject, excelColumn.getProperty(), cellValue);
		}
		return formObject;
	}
	
	// test
	public static void main(String[] args) {
		POIExcelParser p = new POIExcelParser(new XMLExcelMappingParser(), new String[]{"com/googlecode/allinclusive/fw/core/data/input/excel/parser/excel-mappings.xml"});
		ResourceLoader rl = new DefaultResourceLoader();
		Map<String, Object> errorMaps = new HashMap<String, Object>();
		List<Form> forms = p.parse(ExampleForm.class, new Resource[]{rl.getResource("classpath:com/googlecode/allinclusive/fw/core/data/input/excel/parser/excel-data.xlsx")}, errorMaps);
		System.out.println(forms);
	}
}
